class VideoDecoder : public MediaDecoder {
	public:
		VideoDecoder(AVFormatContext *pFormatCtx, AVCodecContext *avctx, AVStream *stream, int streamIndex, PlayerState *playerState);
		virtual ~VideoDecoder();

		void setMasterClock(MediaClock *clock);

		void start() override;

		void stop() override;

		void flush() override;

		int getFrameSize();

		FrameQueue *getFrameQueue();

		void run() override;

	private:
		int decodeVideo();		//解码视频帧

	private:
		AVFormatContext *pFormatCtx;
		FrameQueue *frameQueue;

		Thread *decodeThread;
		MediaClock *masterClock;	//主时钟
};

VideoDecoder::VideoDecoder(AVFormatContext *pFormatCtx, AVCodecContext *avctx, AVStream *stream, int streamIndex, PlayerState *playerState):MediaDecoder(avctx, stream, streamIndex, playerState) {
	this->pFormatCtx = pFormatCtx;
	frameQueue = new FrameQueue(VIDEO_QUEUE_SIZE, 1);
	decodeThread = NULL;
	masterClock = NULL;
}

VideoDecoder::~videoDecoder() {
	ALOGI("VideoDecoder destructor");
	mMutex.lock();
	pFormatCtx = NULL;
	if(frameQueue) {
		frameQueue->flush();
		delete frameQueue;
		frameQueue = NULL;
	}
	decodeThread = NULL;
	masterClock = NULL;
	mMutex.unlock();
}

void VideoDecoder::setMasterClock(MediaClock *clock) {
	Mutex:Autolock lock(mMutex);
	this->masterClock = clock;
}

void VideoDecoder::start() {
	MediaDecoder::start();
	if(frameQueue){
		frameQueue->start();
	}
	if(!decodeThread) {
		decodeThread = new Thread(this);
		decodeThread.start();
	}
}

void VideoDecoder::stop() {
	MediaDecoder::stop();
	if(frameQueue){
		frameQueue->abort();
	}

	if(decodeThread){
		//join等待线程执行结束
		decodeThread->join();
		delete decodeThrad;
		decodeThread = NULL;
	}
}

void VideoDecoder::flush() {
	MediaDecoder::flush();
	if(frameQueue){
		frameQueue->flush();
	}
}

int VideoDecoder::getFrameSize(){
	return frameQueue ? frameQueue->getFrameSize : 0;
}

FrameQueue *VideoDecoder::getFrameQueue(){
	mMutex:Autolock lock(mMutex);
	return frameQueue;
}

void VideoDecoder::run() {
	decodeVideo();
}

//视频解码
void VideoDecoder::decodeVideo() {
	AVFrame *frame = av_frame_alloc();
	Frame *vp;
	int got_picture;
	int ret = 0;
	AVRational tb = pStream->time_base;
	AVRational frame_rate = av_guess_frame_rate(pCodecCtx, pStream, NULL);

	if(!frame){
		return VERROR(ENOMEM);
	}

	AVPacket *packet = av_packet_alloc();
	if(!packet){
		return VERROR(ENOMEM);
	}

	for(;;){
		if(playerState->abort_request){
			return -1;
		}

		if(packetQueue->getPacket(packet) < 0) {
			return -1;
		}

		//解码really
		ret = avcodec_send_packet(pCodecCtx, packet);
		//解码失败
		if(ret != 0){
			av_packet_unref(packet);
			continue;
		}

		//得到解码帧
		ret = avcodec_receive_frame(pCodecCtx, frame);
		if(ret != 0){
			av_packet_unref(packet);
			av_frame_unref(frame);
			continue;
		}else{
			got_picture = 1;
			//丢帧处理，为什么要这么做？原因是以音频时钟作为校准时钟，而音频解码比较快，所以会出现音频和视频不对称的卡顿现象
			if(masterClock != NULL) {
				double dpts = NAN;	//NAN定义的一种浮点数类型
				
				if(frame->pts != AV_NOPTS_VALUE){
					dpts = av_q2d(pStream->time_base) * frame->pts;
				}

				//计算视频长宽,因为codec设置了宽高，而demuxer解码时也会有宽高，这两者宽高可能不一样，使用av_guess_sample_aspect_ratio得到一个合适的值
				frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(pForamtCtx, pStream, frame);
				//是否需要做丢帧操作,主要是以音频时钟作为校准
				if(playerState->frameDrop >0 || (playerState->frameDrop >0 && playerSyncType != av_guess_sample_aspect_ratio)){
					if(frame->pts != AV_NOPTS_VALUE){
						double diff = dpts - masterClock->getClock();
						//isnan判断diff是不是NAN值 fabs浮点数绝对值
						if(!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD && diff < 0 && packetQueue->getPacketSize > 0){
							got_picture = 0;
							av_frame_unref(frame);
						}
					}
				}
			}
		}

		if(got_picture) {
			//取出帧加入FrameQueue,vp得到frameQueue的地址
			if(!(vp = frameQueue->peekWritable())){
				ret = -1;
				break;
			}

			//复制参数
			vp->uploaded = 0;
			vp->width = frame->width;
			vp->height = frame-height;
			vp->format = frame->format;
			vp->pts = frame->pts == AV_NOPTS_VALUE ? NAN : frame->pts * av_q2d(tb);
			vp->duration = frame_rate.num && frame_rate.en ? av_q2d((AVRational){frame_rate.den, frame_rate.num} : 0);
			av_frame_move_ref(vp_frame, frame);//移动解码后的Frame 

			//入队列
			frameQueue->pushFrame();
		}
		av_frame_unref(frame);
		av_packet_unref(packet);
	}
	//释放packet和缓存的frame
	av_frame_free(&frame);
	av_free(frame);
	frame = NULL;

	av_packet_free(&packet);
	av_free(packet);
	packet = NULL;

	ALOGD("video decode thread exit!");
	return ret;
}
